package terra.model.map;

import terra.Config;
import terra.managers.MapManager;
import terra.managers.WeatherManager;
import terra.model.World;
import terra.model.object.GameObject;
import terra.model.object.NpcObject;
import terra.model.object.map.AbstractMapObject;
import terra.util.MathUtil;

public class MapCreater implements Runnable {
	int index;

	public MapCreater(int index) {
		this.index = index;
	}

	@Override
	public void run() {
		MapManager.getInstance().getWaitingMaps().add(index);
		Map map = new Map();
		map.index = index;
		map.setMap(new AbstractMapObject[Config.mapWidth][Config.mapHeight]);

		int terrainDestruct = 2 + MathUtil.rnd.nextInt(3);
		int meter = Config.mapHeight / 2 + Config.mapHeight / 8;
		int lastMeter;
		// переменная otherWay создана для случая с картами, которые нужно
		// создавать не слева направо, а справа налево.
		boolean otherWay = false;
		if (!MapManager.getInstance().getMaps().containsKey((index - 1))
				&& MapManager.getInstance().init)
			otherWay = true;
		if (MapManager.getInstance().getMaps().containsKey((index - 1)))
			meter = MapManager.getInstance().getMaps().get(index - 1).container.meterRight;

		if (MapManager.getInstance().getMaps().containsKey(index + 1))
			meter = MapManager.getInstance().getMaps().get(index + 1).container.meterLeft;
		lastMeter = meter;

		if (otherWay)
			map.container.meterRight = lastMeter;
		else
			map.container.meterLeft = lastMeter;
		int curX = 0;
		if (otherWay)
			curX = Config.mapWidth - 1;
		int b = randomRange(-terrainDestruct, terrainDestruct);
		int a = randomRange(-b, b);
		for (int w = 0; w < Config.mapWidth; w++) {
			map.getGroundLine()[curX] = meter;
			meter = Config.mapHeight;
			if (meter == Config.mapHeight) {
				if (otherWay)
					curX--;
				else
					curX++;
				if (randomRange(0, 100) < 20)
					b = randomRange(-terrainDestruct, terrainDestruct);
				if (randomRange(0, 100) < 50)
					a = randomRange(-b, b);
				lastMeter += a;
				meter = lastMeter;
				// meter+=10;
				terrainDestruct = 2 + MathUtil.rnd.nextInt(3);
			}
		}
		if (otherWay)
			map.container.meterLeft = lastMeter;
		else
			map.container.meterRight = lastMeter;
		MapManager.getInstance().getWaitingMaps().remove((Integer) map.index);
		MapManager.getInstance().mapAdded(map.index);
		MapManager.getInstance().getMaps().put(map.index, map);
		if (MapManager.getInstance().init) {
			MapManager.getInstance().setBiom(map);
			MapManager.getInstance().applyBiom(map);
			for (int x = 0; x < Config.mapWidth; x++)
				World.getInstance().groundListener.checkGround(map.index, x);
			MapManager.getInstance().generateWater(map);
			MapManager.getInstance().generateVerticalCave(map);
		}
		MapManager.getInstance().getWaitingMaps().remove((Object) index);
		map.sendMap(null, true);
		WeatherManager.getInstance().mapCreated(map);
		
		for(GameObject obj: map.getObjects().values()){
			if (obj instanceof NpcObject){
				((NpcObject) obj).insertNpc();
			}
		}
		System.gc();
	}

	private int randomRange(int low, int high) {
		return (int) Math.floor(Math.random() * (1 + high - low)) + low;
	}
}